using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;
using System.Collections.Specialized;
using System.Collections;
using UMC.Data;
using UMC.WorkFlow.Entities;

namespace UMC.WorkFlow.Form
{
    public class TaskButton
    {
        public CommandType Command
        {
            get;
            internal set;
        }
        public string Text
        {
            get;
            internal set;
        }

        public string Id
        {
            get;
            internal set;
        }

        public string ShapeId
        {
            get;
            internal set;
        }
    }

    public class FormManager
    {


        public static TaskResult Progress(UMC.Security.AccessToken token, ulong taskId, CommandType cmd, Hashtable UIData, ulong instanceId)
        {
            return Progress(token, taskId, cmd, UIData, new ulong[] { instanceId })[0];
        }
        public static List<TaskResult> Progress(UMC.Security.AccessToken token, ulong taskId, CommandType cmd, Hashtable UIData, params ulong[] instances)
        {
            var Identity = new Identity(token.Username, token.Alias);
            List<TaskResult> list = new List<TaskResult>();

            foreach (var InstanceId in instances)
            {


                if (cmd == CommandType.Save)
                {
                    // var selecter = UMC.WorkFlow.TaskRuntime.Database.ObjectEntity<TaskRequest>();
                    // selecter.Where.And().Equal(new TaskRequest { InstanceId = InstanceId });


                    if (DataFactory.Instance().TaskRequest(InstanceId) == null)
                    {
                        TaskRequest reg = new TaskRequest
                        {
                            InstanceId = InstanceId,
                            Subject = (UIData["Subject"] ?? FormMessage.TaskData(InstanceId)["Subject"]) as string,
                            TaskId = taskId,
                            Description = UIData["Explain"] as string,
                            StartTime = DateTime.Now,
                            Username = token.Username,
                            Alias = token.Alias,
                            Status = TaskStatus.Prepare
                        };
                        DataFactory.Instance().Put(reg);
                    }
                }
                var result = UMC.WorkFlow.TaskRuntime.Progress(Identity, InstanceId, taskId, cmd, new FormMessage(UIData).OnRespond);
                list.Add(result);
            }
            return list;
        }
        /// <summary>
        /// 得到根据作业命令配置文件，和实例可用命令的可用命令
        /// </summary>
        /// <param name="task">作业实例</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        public static TaskButton[] GetCommands(UMC.WorkFlow.TaskInstance task, UMC.WorkFlow.Identity identity)
        {
            if (task == null)
            {
                throw new System.ArgumentNullException("task");
            }
            return GetCommands(task.TaskId, task, identity);
        }
        /// <summary>
        /// 得到根据作业命令配置文件，得到准备状态下的命令状态
        /// </summary>
        /// <param name="FormId">作业流程id</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        public static TaskButton[] GetCommands(ulong FormId, ulong InstanceId, UMC.WorkFlow.Identity identity)
        {
            var task = UMC.WorkFlow.TaskRuntime.GetInstance(InstanceId);
            return task == null ? FormManager.GetCommands(FormId, identity) : FormManager.GetCommands(task, identity);
        }
        /// <summary>
        /// 得到根据作业命令配置文件，得到准备状态下的命令状态
        /// </summary>
        /// <param name="FormId">作业流程id</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        public static TaskButton[] GetCommands(ulong FormId, UMC.WorkFlow.Identity identity)
        {
            return GetCommands(FormId, null, identity);
        }

        /// <summary>
        /// 检测当前用户的命令是否可用
        /// </summary>
        /// <param name="cmdType">命令</param>
        /// <param name="instance">作业实例</param>
        /// <param name="dentity">身份</param>
        /// <param name="shape">返回的图形结点</param>
        /// <returns></returns>
        static bool CheckCommand(CommandType cmdType, ulong FormId, TaskInstance instance, Identity dentity, out Shape shape)
        {
            shape = null;
            bool retBool = false;
            if (instance == null)
            {
                switch (cmdType)
                {
                    case CommandType.Submit:

                    case CommandType.Save:
                        var task = TaskManager.Form(FormId);
                        retBool = true;

                        shape = task.Shapes.Find(g => !task.Lines.Exists(l => l.ToId == g.Id));

                        break;
                    default:
                        retBool = false;
                        break;
                }
            }
            else
            {
                Predicate<Shape> FindActiveAndIdentity = delegate (Shape spe)
                {
                    if (spe.Status == ShapeStatus.Activation)
                    {
                        if (String.Equals(spe.Identity.Username, dentity.Username, StringComparison.CurrentCultureIgnoreCase))
                        {
                            return true;
                        }
                        else
                        {
                            return spe.Identity.Proxy(dentity, instance.TaskId);
                        }
                    }
                    return false;
                };
                Predicate<Shape> FindRejectAndIdentity = delegate (Shape spe)
                {

                    if (spe.Status == ShapeStatus.Rejected)
                    {
                        if (String.Equals(spe.Identity.Username, dentity.Username, StringComparison.CurrentCultureIgnoreCase))
                        {
                            return true;
                        }
                        else
                        {
                            return spe.Identity.Proxy(dentity, instance.TaskId);
                        }
                    }
                    return false;
                };
                Predicate<Shape> FindLockedAndIdentity = delegate (Shape spe)
                {

                    if (spe.Status == ShapeStatus.Locked)
                    {
                        if (String.Equals(spe.Identity.Username, dentity.Username, StringComparison.CurrentCultureIgnoreCase))
                        {
                            return true;
                        }
                        else
                        {
                            return spe.Identity.Proxy(dentity, instance.TaskId);
                        }
                    }
                    return false;
                };
                switch (instance.Status)
                {
                    //case TaskStatus.Prepare:
                    //    break;
                    case TaskStatus.InReview:

                        shape = instance.Shapes.Find(FindActiveAndIdentity);
                        switch (cmdType)
                        {
                            case CommandType.Apostille:
                                /**    没有找到当前身份的审批者       * **/
                                if (shape == null)
                                {
                                    retBool = false;
                                }
                                else
                                {
                                    /*加签成功*/
                                    retBool = true;
                                }
                                break;
                            case CommandType.Approval:
                                /**    没有找到当前身份的审批者       * **/

                                if (shape == null)
                                {
                                    retBool = false;
                                }
                                else
                                {
                                    retBool = true;
                                }
                                break;
                            case CommandType.Reject:
                                /**
                                 * 有两种情况
                                 * 一 审批者Reject
                                 * 二　申请者Terminate
                                 * 在5月23号改Reject只有审批者才叫Reject的
                                 * 申请者者的终止操作叫Terminate
                                 * **/

                                retBool = (shape != null);

                                break;
                            case CommandType.Lock:
                                retBool = (shape != null);

                                break;
                            case CommandType.Terminate:
                                retBool = TaskEngine.Security(instance.Identity, dentity, instance.TaskId);
                                /*
                                 * 提交者终止，寻找当前一个激活的Shape
                                 */
                                shape = instance.Shapes.Find(s => s.Status == ShapeStatus.Activation);

                                break;
                            default:
                                retBool = false;
                                break;

                        }
                        break;
                    case TaskStatus.Termination:
                        retBool = TaskEngine.Security(instance.Identity, dentity, instance.TaskId);
                        switch (cmdType)
                        {
                            case CommandType.Submit:
                                if (retBool)
                                {
                                    shape = instance.Shapes.Find(s => s.Status == ShapeStatus.Rejected);
                                    if (shape != null)
                                        retBool = true;
                                }
                                break;
                            case CommandType.Approval:
                                shape = instance.Shapes.Find(FindRejectAndIdentity);
                                if (shape != null)
                                {
                                    retBool = true;
                                }
                                else
                                {
                                    retBool = false;
                                }
                                break;
                            case CommandType.Save:
                                if (retBool)
                                {
                                    shape = instance.Shapes.Find(s => s.Status == ShapeStatus.Rejected);
                                    if (shape != null)
                                        retBool = true;// ValidNode(channel, TaskState.Prepare, exmine, out node);
                                }
                                break;
                            case CommandType.Lock:
                                retBool = false;
                                break;
                            default:
                                retBool = false;
                                break;

                        }
                        break;
                    case TaskStatus.Locked:
                        shape = instance.Shapes.Find(FindLockedAndIdentity);
                        switch (cmdType)
                        {
                            case CommandType.Submit:
                                retBool = false;
                                break;
                            case CommandType.Approval:
                                retBool = (shape != null);
                                break;
                            case CommandType.Reject:
                                retBool = (shape != null);
                                break;
                            case CommandType.Save:
                                retBool = false;
                                break;
                            case CommandType.Lock:
                                retBool = false;
                                break;
                            default:
                                retBool = false;
                                break;

                        }
                        break;
                    default:
                        retBool = false;
                        break;
                }
            }
            return retBool;
        }
        static TaskButton[] GetCommands(ulong FormId, UMC.WorkFlow.TaskInstance instance, UMC.WorkFlow.Identity identity)
        {
            var btns = new List<TaskButton>();

            TaskStatus status = instance == null ? TaskStatus.Prepare : instance.Status;

            var commands = new List<TaskCommand>(DataFactory.Instance().TaskCommand(FormId, status));
            // var entity = UMC.WorkFlow.TaskRuntime.Database.ObjectEntity<TaskCommand>();
            // entity.Where.And().Equal(new TaskCommand
            // {
            //     TaskId = FormId,
            //     TaskStatus = status
            // })
            // .Entities.Query(dr => commands.Add(dr));

            Shape shape = null; ;
            string[] cmds = Enum.GetNames(typeof(CommandType));
            for (int i = 0; i < cmds.Length; i++)
            {
                var cmd = (CommandType)Enum.Parse(typeof(CommandType), cmds[i]);
                if (cmd == CommandType.Lock)
                {
                    continue;
                }
                if (CheckCommand(cmd, FormId, instance, identity, out shape))
                {
                    var btn = new TaskButton();
                    btn.Id = cmd.ToString();
                    btn.Command = cmd;
                    btn.Text = cmds[i];

                    if (shape != null)
                    {
                        btn.ShapeId = shape.Id;



                        var cmd2 = commands.Find(g => g.ShapeId == shape.Id && cmd == g.CommandType);
                        if (cmd2 != null)
                        {
                            if (cmd2.Hidden == true)
                            {
                                continue;
                            }
                            else
                            {
                                btn.Text = cmd2.Text;
                                btns.Add(btn);
                                continue;
                            }

                        }

                    }
                    var cmd3 = commands.Find(g => String.Equals(g.ShapeId, "default", StringComparison.CurrentCultureIgnoreCase) && cmd == g.CommandType);
                    if (cmd3 != null)
                    {
                        if (cmd3.Hidden == true)
                        {
                            continue;
                        }
                        else
                        {
                            btn.Text = cmd3.Text;
                        }
                    }
                    else
                    {
                        switch (cmd)
                        {
                            case CommandType.Apostille:
                                btn.Text = "加签";

                                break;
                            case CommandType.Submit:
                                btn.Text = "提交";
                                break;
                            case CommandType.Save:
                                btn.Text = "保存";
                                break;
                            case CommandType.Lock:
                                btn.Text = "锁定";
                                break;
                            case CommandType.Reject:
                                btn.Text = "驳回";
                                break;
                            case CommandType.Approval:
                                btn.Text = "通过";
                                break;
                            case CommandType.Terminate:
                                btn.Text = "终止";
                                break;
                        }
                    }

                    if (cmd == CommandType.Reject)
                    {
                        var indes = instance.Induces.FindAll(li => li.FromId == shape.Id);
                        if (indes.Count > 0)
                        {
                            foreach (var ind in indes)
                            {
                                var btn2 = new TaskButton();

                                btn2.Command = cmd;
                                btn2.Text = ind.Text;
                                btn2.Id = String.Format("{0}.{1}", cmd, ind.ToId);
                                btns.Add(btn2);

                            }
                        }
                        else
                        {
                            btns.Add(btn);
                        }
                    }
                    else
                    {
                        btns.Add(btn);
                    }
                }
            }
            return btns.ToArray();
        }



    }
}
